home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / bin / wifitap < prev    next >
Text File  |  2006-03-29  |  7KB  |  249 lines

  1. #! /usr/bin/env python
  2.  
  3. ########################################
  4. #
  5. # wifitap.py --- WiFi injection tool through tun/tap device
  6. #
  7. # Copyright (C) 2005 Cedric Blancher <sid@rstack.org>
  8. #
  9. # This program is free software; you can redistribute it and/or modify it
  10. # under the terms of the GNU General Public License version 2 as
  11. # published by the Free Software Foundation; version 2.
  12. #
  13. # This program is distributed in the hope that it will be useful, but
  14. # WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. # General Public License for more details.
  17. #
  18. #########################################
  19.  
  20. import os,sys,getopt,struct,re,string
  21.  
  22. # Import Psyco if available to speed up execution
  23. try:
  24.     import psyco
  25.     psyco.full()
  26. except ImportError:
  27.     print "Psyco optimizer not installed, running anyway..."
  28.     pass
  29.  
  30. from socket import *
  31. from fcntl  import ioctl
  32. from select import select
  33. from scapy  import Raw,Ether,PrismHeader,Dot11,Dot11WEP,LLC,SNAP,sendp,conf
  34.  
  35. TUNSETIFF = 0x400454ca
  36. IFF_TAP   = 0x0002
  37. TUNMODE   = IFF_TAP
  38.  
  39. IN_IFACE  = "ath0"
  40. OUT_IFACE = "ath0raw"
  41. HAS_PRISM = 1
  42. WEP       = 0
  43. KEYID     = 0
  44. DEBUG     = 0
  45. VERB      = 0
  46. BSSID     = ""
  47. UBSSID    = ""
  48. WEPKEY    = ""
  49.  
  50.  
  51. def usage(status=0):
  52.     print "Usage: wifitap -b <BSSID> [-o <iface>] [-i <iface> [-p]] [-w <WEP key>"
  53.     print "                          [-k <key id>]] [-d [-v]] [-h]"
  54.     print "     -b <BSSID>    specify BSSID for injection"
  55.     print "     -o <iface>    specify interface for injection (default: ath0raw)"
  56.     print "     -i <iface>    specify interface for listening (default: ath0)"
  57.     print "     -p            listening interface does not provide Prism Headers"
  58.     print "     -w <key>      WEP mode and key"
  59.     print "     -k <key id>   WEP key id (default: 0)"
  60.     print "     -d            activate debug"
  61.     print "     -v            verbose debugging"
  62.     print "     -h            this so helpful output"
  63.     sys.exit(status)
  64.  
  65. opts = getopt.getopt(sys.argv[1:],"b:o:i:w:k:pdvh")
  66.  
  67. for opt,optarg in opts[0]:
  68.     if opt == "-b":
  69.     UBSSID = optarg
  70.     elif opt == "-o":
  71.     OUT_IFACE = optarg
  72.     elif opt == "-i":
  73.     IN_IFACE = optarg
  74.     elif opt == "-p":
  75.         HAS_PRISM = 0
  76.     elif opt == "-w":
  77.     WEP += 1
  78.     WEPKEY = optarg
  79.     elif opt == "-k":
  80.     KEYID = int(optarg)
  81.     elif opt == "-d":
  82.     DEBUG += 1
  83.     elif opt == "-v":
  84.     VERB += 1
  85.     elif opt == "-h":
  86.     usage()
  87.  
  88. if not UBSSID:
  89.     print "\nError: BSSID not defined\n"
  90.     usage()
  91.  
  92. # Match and parse BSSID
  93. if re.match('^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$', UBSSID):
  94.     for i in range(17):
  95.     BSSID += UBSSID[i].lower()
  96. else:
  97.     print "\nError: Wrong format for BSSID\n"
  98.     usage ()
  99.  
  100. if HAS_PRISM:
  101.     print "IN_IFACE:   %s (Prism headers in capture)" % IN_IFACE
  102. else:
  103.     print "IN_IFACE:   %s (no Prism headers in capture)" % IN_IFACE
  104. print "OUT_IFACE:  %s" % OUT_IFACE
  105. print "BSSID:      %s" % BSSID
  106.  
  107. if WEP:
  108.     # Match and parse WEP key
  109.     tmp_key = ""
  110.     if re.match('^([0-9a-fA-F]{2}){5}$', WEPKEY) or re.match ('^([0-9a-fA-F]{2}){13}$', WEPKEY):
  111.     tmp_key = WEPKEY
  112.     elif re.match('^([0-9a-fA-F]{2}[:]){4}[0-9a-fA-F]{2}$', WEPKEY) or re.match('^([0-9a-fA-F]{2}[:]){12}[0-9a-fA-F]{2}$', WEPKEY):
  113.     tmp_key = re.sub(':', '', WEPKEY)
  114.     elif re.match ('^([0-9a-fA-F]{4}[-]){2}[0-9a-fA-F]{2}$', WEPKEY) or re.match ('^([0-9a-fA-F]{4}[-]){6}[0-9a-fA-F]{2}$', WEPKEY):
  115.     tmp_key = re.sub('-', '', WEPKEY)
  116.     else:
  117.     print "\nError : Wrong format for WEP key\n"
  118.     usage()
  119.     g = lambda x: chr(int(tmp_key[::2][x],16)*16+int(tmp_key[1::2][x],16))
  120.     for i in range(len(tmp_key)/2):
  121.     conf.wepkey += g(i)
  122.     print "WEP key:    %s (%dbits)" % (WEPKEY, len(tmp_key)*4)
  123.     if KEYID > 3 or KEYID < 0:
  124.     print "Key id:     %s (defaulted to 0 due to wrong -k argument)" % KEYID
  125.     KEYID = 0
  126.     else:
  127.     print "Key id:     %s" % KEYID
  128. else:
  129.     if KEYID != 0:
  130.     print "WEP not activated, key id ignored"
  131.  
  132. if not DEBUG:
  133.     if VERB:
  134.     print "DEBUG not activated, verbosity ignored"
  135. else:
  136.     print "DEBUG activated"
  137.     if VERB:
  138.     print "Verbose debugging"
  139.  
  140. conf.iface = OUT_IFACE
  141.  
  142. # Here we put a BPF filter so only 802.11 Data/to-DS frames are captured
  143. # We need to know if PrismHeaders are present so we can shift lookup index
  144. if HAS_PRISM:
  145.     s = conf.L2listen(iface = IN_IFACE,
  146.     filter = "link[144]&0xc == 8 and link[145]&0xf == 1")
  147. else:
  148.     s = conf.L2listen(iface = IN_IFACE,
  149.     filter = "link[0]&0xc == 8 and link[1]&0xf == 1")
  150.  
  151. # Open /dev/net/tun in TAP (ether) mode
  152. f = os.open("/dev/net/tun", os.O_RDWR)
  153. ifs = ioctl(f, TUNSETIFF, struct.pack("16sH", "wj%d", TUNMODE))
  154. ifname = ifs[:16].strip("\x00")
  155. print "Interface %s created. Configure it and use it" % ifname
  156.  
  157.  
  158. try:
  159.     while 1:
  160.         r = select([f,s],[],[])[0][0]
  161.  
  162.     # frame from /dev/net/tun
  163.     if r == f:
  164.  
  165.         # tuntap frame max. size is 1522 (ethernet, see RFC3580) + 4
  166.         buf = os.read(f,1526)
  167.             eth_rcvd_frame=Ether(buf[4:])
  168.  
  169.         if DEBUG:
  170.             os.write(1,"Received from %s\n" % ifname)
  171.         if VERB:
  172.             os.write(1,"%s\n" % eth_rcvd_frame.summary())
  173.         
  174.     # Prepare Dot11 frame for injection
  175.         dot11_sent_frame = Dot11(type = "Data",
  176.         FCfield = "from-DS",
  177.         addr1 = eth_rcvd_frame.getlayer(Ether).dst,
  178.         addr2 = BSSID,
  179.         addr3 = eth_rcvd_frame.getlayer(Ether).src)
  180.         if WEP:
  181.         dot11_sent_frame.FCfield |= 0x40
  182.         dot11_sent_frame /= Dot11WEP(iv = "111",
  183.             keyid = KEYID)
  184.         dot11_sent_frame /= LLC(ctrl = 3)/SNAP()/eth_rcvd_frame.getlayer(Ether).payload
  185.  
  186.         if DEBUG:
  187.             os.write(1,"Sending from-DS to %s\n" % OUT_IFACE)
  188.         if VERB:
  189.             os.write(1,"%s\n" % dot11_sent_frame.summary())
  190.     
  191.     # Frame injection :
  192.         sendp(dot11_sent_frame,verbose=0) # Send from-DS frame
  193.  
  194.     # Frame from WiFi network
  195.     else:
  196.  
  197.         # 802.11 maximum frame size is 2346 bytes (cf. RFC3580)
  198.         # However, WiFi interfaces are always MTUed to 1500
  199.         dot11_rcvd_frame = s.recv(2346)
  200.  
  201.     # WEP handling is automagicly done by Scapy if conf.wepkey is set
  202.     # Nothing to do to decrypt (although not yet tested)
  203.     # WEP frames have Dot11WEP layer, others don't
  204.  
  205.         if DEBUG:
  206.         if dot11_rcvd_frame.haslayer(Dot11WEP): # WEP frame
  207.             os.write(1,"Received WEP from %s\n" % IN_IFACE)
  208.         else: # Cleartext frame
  209.             os.write(1,"Received from %s\n" % IN_IFACE)
  210.         if VERB:
  211.             os.write(1,"%s\n" % dot11_rcvd_frame.summary())
  212.  
  213.     #    if dot11_frame.getlayer(Dot11).FCfield & 1: # Frame is to-DS
  214.     # For now, we only take care of to-DS frames...
  215.  
  216.         if dot11_rcvd_frame.getlayer(Dot11).addr1 != BSSID:
  217.         continue
  218.  
  219.     # One day, we'll try to take care of AP to DS trafic (cf. TODO)
  220.     #    else: # Frame is from-DS
  221.     #        if dot11_frame.getlayer(Dot11).addr2 != BSSID:
  222.     #            continue
  223.     #    eth_frame = Ether(dst=dot11_frame.getlayer(Dot11).addr1,
  224.     #           src=dot11_frame.getlayer(Dot11).addr3)
  225.         
  226.         if dot11_rcvd_frame.haslayer(SNAP):
  227.         eth_sent_frame = Ether(dst=dot11_rcvd_frame.getlayer(Dot11).addr3,
  228.             src=dot11_rcvd_frame.getlayer(Dot11).addr2)
  229.         eth_sent_frame.payload = dot11_rcvd_frame.getlayer(SNAP).payload
  230.         eth_sent_frame.type = dot11_rcvd_frame.getlayer(SNAP).code
  231.  
  232.         if DEBUG:
  233.             os.write(1, "Sending to %s\n" % ifname)
  234.             if VERB:
  235.             os.write(1, "%s\n" % eth_sent_frame.summary())
  236.  
  237.     # Add Tun/Tap header to frame, convert to string and send
  238.         buf = "\x00\x00" + struct.pack("!H",eth_sent_frame.type) + str(eth_sent_frame)
  239.         os.write(f, buf)
  240.  
  241. # Program killed
  242. except KeyboardInterrupt:
  243.     print "Stopped by user."
  244.  
  245. s.close()
  246. os.close(f)
  247.  
  248. sys.exit()
  249.